package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.GuiGuCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.context.UpdateUserPaidRecordStrategyContext;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.mapper.UserPaidTrackMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.atguigu.tingshu.user.strategy.UpdateUserPaidRecordStrategy;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes", "unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;
	@Autowired
	WxMaService wxMaService;
	@Autowired
	RedisTemplate<String,String> redisTemplate;

	@Autowired
	private KafkaService kafkaService ;
	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;
	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@SneakyThrows
	@Override
	public String wxLogin(String code) {

		try {
			// 发送请求，校验凭证
			WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
			String openid = sessionInfo.getOpenid();

			// 根据openId查询用户数据
			LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
			lambdaQueryWrapper.eq(UserInfo::getWxOpenId, openid);
			UserInfo userInfo = userInfoMapper.selectOne(lambdaQueryWrapper);
			if (userInfo == null) {
				userInfo = new UserInfo();
				userInfo.setWxOpenId(openid);
				userInfo.setNickname("尚硅谷");
				userInfo.setAvatarUrl("http://192.168.126.128:9000/sph/0741a97e9ca24d2b87f2cf8b80f4db47_png");
				userInfoMapper.insert(userInfo);


				// 初始化新注册的用户的账号信息
				kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER , userInfo.getId().toString());
			}


			//保存用户的登录状态
			String token = UUID.randomUUID().toString().replace("-", "");
			userInfo.setPassword(null);
			redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token, JSON.toJSONString(userInfo));
			return token;
		}catch (Exception e) {
			e.printStackTrace();
			throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);

		}
	}

	@Override
	public UserInfoVo getUserInfo() {
		//获取用户id
		Long userId = AuthContextHolder.getUserId();
		//获取用户信息
		UserInfo selectById = userInfoMapper.selectById(userId);
		if (userId!=null){
			//封装数据
			UserInfoVo userInfovo = new UserInfoVo();
			userInfovo.setId(userId);
			userInfovo.setNickname(selectById.getNickname());
			userInfovo.setAvatarUrl(selectById.getAvatarUrl());
			userInfovo.setIsVip(selectById.getIsVip());
			userInfovo.setVipExpireTime(selectById.getVipExpireTime());
			userInfovo.setWxOpenId(selectById.getWxOpenId());
			return userInfovo;
		}

		return null;
	}

	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIds) {

		//创建map对象封装响应结果数据
		Map<Long, Integer> map = new HashMap<>();
		//获取用户id
		Long userId = AuthContextHolder.getUserId();
		//判断是否购买过次专辑
		LambdaQueryWrapper<UserPaidAlbum> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(UserPaidAlbum::getUserId, userId);
		lambdaQueryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(lambdaQueryWrapper);
		if (userPaidAlbum!=null){
		trackIds.stream().forEach(trackId -> map.put(trackId, 1));
		}else {//该用户未购买过次专辑，查询是否单独购买过声音
			LambdaQueryWrapper<UserPaidTrack> UserPaidTracklambdaQueryWrapper = new LambdaQueryWrapper<>();
			UserPaidTracklambdaQueryWrapper.eq(UserPaidTrack::getUserId,userId );
			UserPaidTracklambdaQueryWrapper.eq(UserPaidTrack::getAlbumId, albumId);
			//用户购买的所有声音
			List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(UserPaidTracklambdaQueryWrapper);
			if (StringUtils.isEmpty(userPaidTracks)){
				//未购买声音
				trackIds.stream().forEach(trackId -> map.put(trackId, 0));

			}else {
				//遍历用户购买的声音
				List<Long> longList = userPaidTracks.stream().map(UserPaidTrack -> UserPaidTrack.getTrackId()).collect(Collectors.toList());
				//判断当前声音是否在购买的声音当中
				trackIds.stream().forEach(trackId -> {
					if (longList.contains(trackId)){
						map.put(trackId,1);//购买过当前声音
					}else {
						map.put(trackId,0);//未购买过当前声音
					}
				});



			}

		}		return map;
	}

	@GuiGuCache(cacheKey = "user:info:" + "#{#params[0]}")
	@Override
	public UserInfoVo findUserInfoVoByUserId(Long userId) {
		UserInfo userInfo = this.getById(userId);
		UserInfoVo userInfoVo = new UserInfoVo() ;
		BeanUtils.copyProperties(userInfo , userInfoVo);
		return userInfoVo;
	}

	@Override
	public List<Long> findUserPaidTrackList(Long album) {
		//根据用户Id以及专辑Id查询用户购买的声音列表
		Long userId = AuthContextHolder.getUserId();
		LambdaQueryWrapper<UserPaidTrack> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(UserPaidTrack::getUserId, userId);
		lambdaQueryWrapper.eq(UserPaidTrack::getAlbumId, album);
		lambdaQueryWrapper.select(UserPaidTrack::getTrackId); //指定查询的列数据
		List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(lambdaQueryWrapper);
		List<Long> collect = userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
		return collect;
	}

	@Override
	public void updateUserPaidRecord(UserPaidRecordVo userPaidRecordVo) {
		// 根据付款项目的类型保存交易信息【策略设计模式进行改造】
		String itemType = userPaidRecordVo.getItemType();
		UpdateUserPaidRecordStrategy updateUserPaidRecordStrategy = UpdateUserPaidRecordStrategyContext.getUpdateUserPaidRecordStrategy(itemType);
		updateUserPaidRecordStrategy.updateUserPaidRecord(userPaidRecordVo) ;
	}

	@Override
	public void updateVipExpireStatus() {
		// 根据isVip以及vipExpireTime字段进行查询
		LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
		lambdaQueryWrapper.eq(UserInfo::getIsVip, 1) ;
		lambdaQueryWrapper.lt(UserInfo::getVipExpireTime , new Date()) ;
		List<UserInfo> userInfoList = userInfoMapper.selectList(lambdaQueryWrapper);

		List<UserInfo> userInfos = userInfoList.stream().map(userInfo -> {
			userInfo.setIsVip(0);
			return userInfo;
		}).collect(Collectors.toList());

		this.updateBatchById(userInfos) ;
	}


}
